package com.ev.system.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ev.framework.config.Constant;
import com.ev.framework.utils.ShiroUtils;
import com.ev.framework.utils.StringUtils;
import com.ev.system.dao.*;
import com.ev.system.domain.*;
import com.ev.system.service.DeptService;
import com.ev.system.service.RoleService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;


@Service
public class RoleServiceImpl implements RoleService {

    public static final String ROLE_ALL_KEY = "\"role_all\"";

    public static final String DEMO_CACHE_NAME = "role";

    @Autowired
    RoleDao roleMapper;
    @Autowired
    RoleMenuDao roleMenuMapper;
    @Autowired
    UserDao userMapper;
    @Autowired
    private DeptService deptService;
    @Autowired
    UserRoleDao userRoleMapper;
    @Autowired
    RoleDataDao roleDataMapper;

    @Override
    public List<RoleDO> list() {
        List<RoleDO> roles = roleMapper.list(new HashMap<>(16));
        return roles;
    }


    @Override
    public List<RoleDO> list(Long userId) {
        List<Long> rolesIds = userRoleMapper.listRoleId(userId);
        List<RoleDO> roles = roleMapper.list(new HashMap<>(16));
        for (RoleDO roleDO : roles) {
            roleDO.setRoleSign("false");
            for (Long roleId : rolesIds) {
                if (Objects.equals(roleDO.getRoleId(), roleId)) {
                    roleDO.setRoleSign("true");
                    break;
                }
            }
        }
        return roles;
    }
    @Transactional
    @Override
    public int save(RoleDO role) {
        int count = roleMapper.save(role);
        List<Long> ids = Lists.newArrayList();
        List<Long> menuIds = role.getMenuIds();
        List<Long> appMenuIds = role.getAppMenuIds();
        List<Long> padMenuIds = role.getPadMenuIds();
        if (menuIds != null) {
            ids.addAll(menuIds);
        }
        if(appMenuIds!=null){
            ids.addAll(appMenuIds);
        }
        if(padMenuIds!=null){
            ids.addAll(padMenuIds);
        }
        if (ids.size()>0) {
            Long roleId = role.getRoleId();
            List<RoleMenuDO> rms = new ArrayList<>();
            for (Long menuId : ids) {
                RoleMenuDO rmDo = new RoleMenuDO();
                rmDo.setRoleId(roleId);
                rmDo.setMenuId(menuId);
                rms.add(rmDo);
            }
            roleMenuMapper.removeByRoleId(roleId);
            if (rms.size() > 0) {
                roleMenuMapper.batchSave(rms);
            }
        }
        return count;
    }

    @Transactional
    @Override
    public int remove(Long id) {
        if (isUserUse(id)){
            return -1;
        }
        int count = roleMapper.remove(id);
        userRoleMapper.removeByRoleId(id);
        roleMenuMapper.removeByRoleId(id);
        roleDataMapper.deleteByRoleId(id);
        return count;
    }

    @Override
    public boolean isUserUse(Long id) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("roleId",id);
        return userRoleMapper.count(map)>0;
    }

    @Override
    public boolean checkSave(RoleDO role) {
        return roleMapper.checkSave(role)==0;
    }

    @Override
    public Map<String, Object> getDataPermission(Integer type) {
        // 1 客户 2 供应商 3 员工
        Map<String, Object> params = Maps.newHashMap();
        if (type == null) {
            return params;
        }
        if (type == 1 || type == 2 || type == 3) {
            String typeToString = String.valueOf(type);
            UserDO userDO = ShiroUtils.getUser();
            if (userDO != null) {
                Long userId = userDO.getUserId();
                Map<String, String> dataPermission = userDO.getDataPermission();
                Map<String, List<Long>> deptData = userDO.getDeptData();

                String perm = dataPermission.get(typeToString);
                // 全部权限
                if (Objects.equals(perm, Constant.ALL_DATA.toString())) {
                    return params;
                }
                // 个人
                if (Objects.equals(perm, Constant.PERSONAL_DATA.toString())) {
                    params.put("userId", userId);
                    return params;
                }

                // 有部门权限的
                List<String> dataPermissionList = Lists.newArrayList();
                dataPermissionList.add("0");
                dataPermissionList.add("-1");
                dataPermissionList.add("-2");
                dataPermissionList.add(Constant.SUBORDINATE_DEPT_DATA.toString());
                dataPermissionList.add(Constant.THIS_DEPT_DATA.toString());
                dataPermissionList.add(Constant.CUSTOM_DATA.toString());
                if (dataPermissionList.contains(perm)) {
                    List<Long> deptList = deptData.get(typeToString);
                    if (deptList.size() > 0) {
                        params.put("deptData", deptList);
                    }
                    // 若是个人 + 自定义数据权限
                    if (Objects.equals(perm, "-2")) {
                        params.put("userIdSingle", userId);
                    }
                }
            }
        }
        return params;
    }

    @Override
    public RoleDO get(Long id) {
        RoleDO roleDO = roleMapper.get(id);
        return roleDO;
    }

    @Override
    public int update(RoleDO role) {
        int r = roleMapper.update(role);
        List<Long> ids = Lists.newArrayList();
        List<Long> menuIds = role.getMenuIds();
        List<Long> appMenuIds = role.getAppMenuIds();
        List<Long> padMenuIds = role.getPadMenuIds();
        if (menuIds != null) {
            ids.addAll(menuIds);
        }
        if(appMenuIds!=null){
            ids.addAll(appMenuIds);
        }
        if(padMenuIds!=null){
            ids.addAll(padMenuIds);
        }
        Long roleId = role.getRoleId();
        roleMenuMapper.removeByRoleId(roleId);

        if (ids.size()>0){
            List<RoleMenuDO> rms = new ArrayList<>();
            for (Long menuId : ids) {
                RoleMenuDO rmDo = new RoleMenuDO();
                rmDo.setRoleId(roleId);
                rmDo.setMenuId(menuId);
                rms.add(rmDo);
            }
            if (rms.size() > 0) {
                roleMenuMapper.batchSave(rms);
            }
        }
        return r;
    }

    @Override
    public int batchremove(Long[] ids) {
        for (Long id : ids) {
            if (this.isUserUse(id)) {
                return -1;
            }
        }
        int r = roleMapper.batchRemove(ids);
        return r;
    }

    @Override
    public RoleDO getRByName(String name) {
        RoleDO roleDO = roleMapper.getRByName(name);
        return roleDO;
    }

    @Override
    public List<RoleDO> getRoleListByUserId(Long userId) {
        List<Long> userRoleDoList = userRoleMapper.listRoleId(userId);
        List<RoleDO> roleList = roleMapper.getByIds(userRoleDoList);
        return roleList;
    }

    @Transactional
    @Override
    public int insert(RoleDO role) {
        int save = this.save(role);
        Long roleId = role.getRoleId();
        String dataPermission = role.getDataPermission();
        if(dataPermission != null){
            List<RoleDataDO> roleDataDOList = Lists.newArrayList();
            RoleDataDO roleDataDO;
            JSONArray jsonArray = JSON.parseArray(dataPermission);
            for (Object o : jsonArray) {
                JSONObject jsonObject = (JSONObject)o;
                Integer type = jsonObject.getInteger("type");
                Long dataPermissionSingle = jsonObject.getLong("dataPermission");
                if (Objects.equals(dataPermissionSingle,Constant.CUSTOM_DATA)){
                    String deptIds = jsonObject.getString("deptIds");
                    if(StringUtils.isNoneEmpty(deptIds)){
                        ArrayList<String> deptIdList = Lists.newArrayList(deptIds.split(","));
                        for (String id : deptIdList) {
                            if(StringUtils.isEmpty(id)){
                                continue;
                            }
                            roleDataDO = new RoleDataDO();
                            roleDataDO.setDeptId(Long.parseLong(id));
                            roleDataDO.setRoleId(roleId);
                            roleDataDO.setType(type);
                            roleDataDOList.add(roleDataDO);
                        }
                    }
                }
            }
            if (roleDataDOList.size() > 0) {
                roleDataMapper.batchSave(roleDataDOList);
            }

        }
        return save;
    }

    @Override
    public int edit(RoleDO role) {
        int update = this.update(role);
        Long roleId = role.getRoleId();
        // 先删后增
        roleDataMapper.deleteByRoleId(roleId);
        String dataPermission = role.getDataPermission();
        if(dataPermission != null){
            RoleDataDO roleDataDO;
            List<RoleDataDO> roleDataDOList = Lists.newArrayList();
            JSONArray jsonArray = JSON.parseArray(dataPermission);
            for (Object o : jsonArray) {
                JSONObject jsonObject = (JSONObject)o;
                Integer type = jsonObject.getInteger("type");
                Long dataPermissionSingle = jsonObject.getLong("dataPermission");
                if (Objects.equals(dataPermissionSingle,Constant.CUSTOM_DATA)){
                    String deptIds = jsonObject.getString("deptIds");
                    if (StringUtils.isNoneEmpty(deptIds)) {
                        ArrayList<String> deptIdList = Lists.newArrayList(deptIds.split(","));
                        for (String id : deptIdList) {
                            roleDataDO = new RoleDataDO();
                            roleDataDO.setDeptId(Long.parseLong(id));
                            roleDataDO.setRoleId(roleId);
                            roleDataDO.setType(type);
                            roleDataDOList.add(roleDataDO);
//                            roleDataMapper.save(roleDataDO);
                        }
                    }
                }
            }
            if (roleDataDOList.size() > 0) {
                roleDataMapper.batchSave(roleDataDOList);
            }

        }
        return update;
    }

}
